package cn.elwy.rcp.ui.table;

import java.util.HashMap;
import java.util.List;

import org.eclipse.jface.util.LocalSelectionTransfer;
import org.eclipse.jface.viewers.CheckboxTreeViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.ui.dialogs.ContainerCheckedTreeViewer;

import cn.elwy.rcp.ui.table.internal.TableColumnSortListener;
import cn.elwy.rcp.ui.table.listener.TablePaneCheckStateListener;
import cn.elwy.rcp.ui.table.listener.TableTreePaneDragSourceListener;
import cn.elwy.rcp.ui.table.listener.TableTreePaneDropTargetListener;
import cn.elwy.rcp.ui.table.model.ColumnInfo;
import cn.elwy.rcp.ui.table.model.TableInfo;
import cn.elwy.rcp.ui.table.provider.TablePaneCheckStateProvider;
import cn.elwy.rcp.ui.table.setting.listener.ColumnResizeListener;
import cn.elwy.rcp.ui.table.util.ColumnVisibleUtil;
import cn.elwy.rcp.ui.util.SWTUtil;

public class TreeViewerPane extends TablePane {

  protected TreeViewer treeViewer;
  Tree tree;

  protected TreeViewerPane(Composite parent, String tableId) {
    super(parent, SWT.NONE, tableId);
  }

  protected TreeViewerPane(Composite parent, int style, String tableId) {
    super(parent, style, tableId);
  }

  protected TreeViewerPane(Composite parent, int style, TableInfo tableInfo) {
    super(parent, style, tableInfo);
  }

  @Override
  protected void createTableViewer() {
    TablePaneCheckStateProvider checkStateProvider = tableInfo.getCheckStateProvider();
    if (checkStateProvider == null) {
      treeViewer = new TreeViewer(this, getStyle());
    } else {
      treeViewer = new ContainerCheckedTreeViewer(this, getStyle());
      ((ContainerCheckedTreeViewer) treeViewer).setCheckStateProvider(checkStateProvider);
    }

    tree = treeViewer.getTree();
    tree.setLayoutData(new GridData(GridData.FILL_BOTH));
  }

  @Override
  protected void createColumns() {
    treeColumnMap = new HashMap<String, Item>();
    if (tableInfo.isTree()) {
      return;
    }

    boolean canSettingColumn = tableInfo.isCanSettingColumn();
    List<ColumnInfo> columnInfos = tableInfo.getColumnInfoList();
    for (ColumnInfo columnInfo : columnInfos) {
      int style = SWTUtil.toSWTConstant(columnInfo.getStyleName());
      TreeViewerColumn treeColumn = new TreeViewerColumn(treeViewer, style);
      TreeColumn column = treeColumn.getColumn();
      column.setText(columnInfo.getName());
      column.setWidth(columnInfo.getWidth());
      int alignment = SWTUtil.toSWTConstant(columnInfo.getAlignmentName());
      column.setAlignment(alignment);
      column.setData(ColumnVisibleUtil.DEFAULT_COLUMN_WIDTH, columnInfo.getWidth());
      column.setData(columnInfo.getId());
      column.setData("columnInfo", columnInfo);
      column.setMoveable(true);
      column.setResizable(true);
      ColumnVisibleUtil.setColumnVisible(column, columnInfo.isVisible());
      if (canSettingColumn) {
        ColumnResizeListener listener = new ColumnResizeListener();
        listener.setTablePane(this);
        column.addControlListener(listener);
      }
      treeColumnMap.put(columnInfo.getId(), column);
    }
  }

  @Override
  protected void addColumnSortListener() {
    TreeColumn[] columns = tree.getColumns();
    for (TreeColumn column : columns) {
      column.addSelectionListener(new TableColumnSortListener(treeViewer));
    }
  }

  @Override
  protected void addCheckStateListener() {
    TablePaneCheckStateListener checkStateListener = tableInfo.getCheckStateListener();
    if (checkStateListener != null && treeViewer instanceof CheckboxTreeViewer) {
      checkStateListener.setTablePane(this);
      ((CheckboxTreeViewer) treeViewer).addCheckStateListener(checkStateListener);
    }
  }

  @Override
  protected void addDropListener() {
    DropTarget dropTarget = new DropTarget(getTable(), DND.DROP_MOVE);
    dropTarget.setTransfer(new Transfer[] { LocalSelectionTransfer.getTransfer() });
    dropTarget.addDropListener(new TableTreePaneDropTargetListener(getTableViewer()));
  }

  @Override
  protected void addDragListener() {
    DragSource dragSource = new DragSource(getTable(), DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK);
    dragSource.setTransfer(new Transfer[] { LocalSelectionTransfer.getTransfer() });
    dragSource.addDragListener(new TableTreePaneDragSourceListener(getTableViewer()));
  }

  @Override
  public TreeViewer getTableViewer() {
    return treeViewer;
  }

  @Override
  public Tree getTable() {
    return tree;
  }

  @Override
  public int[] getColumnOrder() {
    return tree.getColumnOrder();
  }

  @Override
  public void setColumnOrder(int[] columnOrder) {
    tree.setColumnOrder(columnOrder);
  }

  @Override
  public Item[] getColumns() {
    return tree.getColumns();
  }
}